package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"sync"
	"time"
)

func walkDir3(dir string, filesize chan<- int64, wg *sync.WaitGroup) {
	defer wg.Done()
	for _, entry := range dirents3(dir) {
		if entry.IsDir() {
			wg.Add(1)
			subDir := filepath.Join(dir, entry.Name())
			go walkDir3(subDir, filesize, wg)
		} else {
			fileinfo, _ := entry.Info()
			filesize <- fileinfo.Size()
		}

	}
}

func dirents3(dir string) []os.DirEntry {
	entries, err := os.ReadDir(dir)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	//
	return entries
}

var verbose3 = flag.Bool("v", false, "show verbose progress messages")

func main() {
	flag.Parse()
	roots := flag.Args()
	if len(roots) == 0 {
		fmt.Fprintln(os.Stderr, len(roots))
		return
	}

	//
	var wg sync.WaitGroup
	filesizes := make(chan int64)
	for _, root := range roots {
		wg.Add(1)
		go walkDir3(root, filesizes, &wg)
	}

	var tick <-chan time.Time
	if *verbose3 {
		tick = time.Tick(500 * time.Millisecond)
	}

	var nbytes, nfiles int64

loop:
	for {
		select {
		case size, ok := <-filesizes:
			if !ok {
				break loop
			}
			nfiles++
			nbytes += size
		case <-tick:
			printDiskUsage3(nfiles, nbytes)

		}
	}

	printDiskUsage3(nfiles, nbytes)
}

func printDiskUsage3(nfiles, nbytes int64) {
	fmt.Printf("%d files   %1.f GB\n", nfiles, float64(nbytes)/1e9)
}
